/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.func.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.FunCopyType;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.StringUtil;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.service.common.MetaBeanService;
import com.je.meta.service.func.MetaFuncRelyonService;
import com.je.meta.service.table.MetaResColumnService;
import com.je.meta.service.table.MetaResFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;

@Service
public class MetaFuncRelyonServiceImpl implements MetaFuncRelyonService {

    private static final Logger logger = LoggerFactory.getLogger(MetaFuncRelyonServiceImpl.class);

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private MetaBeanService metaBeanService;
    @Autowired
    private MetaResColumnService metaResColumnService;
    @Autowired
    private MetaResFieldService metaResFieldService;

    @Override
    @Transactional
    public void saveRelyon(DynaBean funcInfo, String type, String funcId) {
        DynaBean fr = new DynaBean("JE_CORE_FUNCRELYON", false);
        fr.set(BeanService.KEY_PK_CODE, "JE_CORE_FUNCRELYON_ID");
        fr.set("FUNCRELYON_FUNCNAME", funcInfo.get("FUNCINFO_FUNCNAME"));
        fr.set("FUNCRELYON_FUNCCODE", funcInfo.get("FUNCINFO_FUNCCODE"));
        fr.set("FUNCRELYON_FUNCID", funcInfo.get("JE_CORE_FUNCINFO_ID"));
        fr.set("FUNCRELYON_RELYTYPE", FunCopyType.ZXRLJ);
        fr.set("FUNCRELYON_REGARD", type);
        fr.set("FUNCRELYON_FUNCINFO_ID", funcId);
        commonService.buildModelCreateInfo(fr);
        metaService.insert(fr);
    }

    @Override
    @Transactional
    public void doSave(String tableCode, String funcId, DynaBean dynaBean) {
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            insertTarget(tableCode, reylonFunc, dynaBean);
            //递归
            doSave(tableCode, reylonFunc.getStr("JE_CORE_FUNCINFO_ID"), dynaBean);
        }
    }

    @Override
    @Transactional
    public void doUpdate(String tableCode, String funcId, DynaBean dynaBean) {
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            updateTarget(tableCode, reylonFunc, dynaBean);
            //递归
            doUpdate(tableCode, reylonFunc.getStr("JE_CORE_FUNCINFO_ID"), dynaBean);
        }
    }

    @Override
    public DynaBean getUpdateBean(String tableCode, DynaBean newBean, DynaBean oldBean) {
        DynaBean resourceTable = metaBeanService.getResourceTable(tableCode);
        String code = getCode(tableCode);
        String foreignCode = getforeignCode(tableCode);
        List<DynaBean> columns = (List<DynaBean>) resourceTable.get(BeanService.KEY_TABLE_COLUMNS);
        for (DynaBean column : columns) {
            String columnCode = column.getStr("TABLECOLUMN_CODE");
            if (code.equals(columnCode) || foreignCode.equals(columnCode)) {
                continue;
            }
            String newValue = newBean.getStr(columnCode, "");
            String oldValue = oldBean.getStr(columnCode, "");
            if (newValue.equals(oldValue)) {
                newBean.remove(columnCode);
            }
        }
        return newBean;
    }

    @Override
    @Transactional
    public void doUpdateList(String tableCode, String funcId, List<DynaBean> beans) {
        if (beans.size() <= 0) {
            return;
        }
        if (StringUtil.isEmpty(funcId)) {
            funcId = beans.get(0).getStr(getforeignCode(tableCode));
        }
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        String pkCode = metaBeanService.getPKeyFieldNames(tableCode);
        for (DynaBean reylonFunc : reylonFuncs) {
            //列表更新软链接对象
            for (DynaBean bean : beans) {
                String pkValue = bean.getStr(pkCode);
                if (StringUtil.isNotEmpty(pkValue)) {
                    updateTarget(tableCode, reylonFunc, bean);
                }
//				else{只有更新操作
//					insertTarget(tableCode, reylonFunc, bean);
//				}
            }
            doUpdateList(tableCode, reylonFunc.getStr("JE_CORE_FUNCINFO_ID"), beans);
        }
    }

    @Override
    @Transactional
    public void doRemove(String tableCode, String funcId, String ids, List<DynaBean> beans) {
        if (beans == null) {
            if (StringUtil.isEmpty(ids)) {
                return;
            }
            String pkCode = metaBeanService.getPKeyFieldNames(tableCode);
            String foreignCode = getforeignCode(tableCode);
            beans = metaService.select(tableCode, ConditionsWrapper.builder().apply(" AND " + pkCode + " IN (" + StringUtil.buildArrayToString(ids.split(",")) + ")"));
            funcId = beans.get(0).getStr(foreignCode);
        }

        //此处微服务改造，暂时注释
//        if("JE_CORE_RESOURCEBUTTON".equals(tableCode)){
//            permissionManager.clearPermData(PermType.BUTTON,ids,false);
//        }
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            removeTarget(tableCode, reylonFunc, beans);
            doRemove(tableCode, reylonFunc.getStr("JE_CORE_FUNCINFO_ID"), "", beans);
        }
    }

    @Override
    @Transactional
    public void doImpl(String funcId) {
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            metaResColumnService.impl(reylonFunc);
            doImpl(reylonFunc.getStr("JE_CORE_FUNCINFO_ID"));
        }
    }

    @Override
    @Transactional
    public void doSyncColumn(String funcId) {
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            DynaBean bean = new DynaBean("JE_CORE_RESOURCEFIELD", false);
            bean.set(BeanService.KEY_PK_CODE, "JE_CORE_RESOURCEFIELD_ID");
            bean.set("RESOURCEFIELD_FUNCINFO_ID", reylonFunc.getStr("RESOURCEFIELD_FUNCINFO_ID"));
            metaResFieldService.doSync(bean);
            doSyncColumn(reylonFunc.getStr("JE_CORE_FUNCINFO_ID"));
        }
    }

    @Override
    @Transactional
    public void doSyncField(String funcId) {
        List<DynaBean> reylonFuncs = getRelyons(funcId);
        for (DynaBean reylonFunc : reylonFuncs) {
            DynaBean bean = new DynaBean("JE_CORE_RESOURCECOLUMN", false);
            bean.set(BeanService.KEY_PK_CODE, "JE_CORE_RESOURCECOLUMN_ID");
            bean.set("RESOURCECOLUMN_FUNCINFO_ID", reylonFunc.getStr("RESOURCECOLUMN_FUNCINFO_ID"));
            metaResColumnService.doSync(bean);
            doSyncField(reylonFunc.getStr("JE_CORE_FUNCINFO_ID"));
        }
    }

    @Override
    @Transactional
    public void removeTarget(String tableCode, DynaBean softFunc, List<DynaBean> beans) {
        String codeName = "";
        String foreignCode = getforeignCode(tableCode);
        if ("JE_CORE_RESOURCECOLUMN".equals(tableCode)) {
            codeName = "RESOURCECOLUMN_CODE";
        } else if ("JE_CORE_RESOURCEFIELD".equals(tableCode)) {
            codeName = "RESOURCEFIELD_CODE";
        } else if ("JE_CORE_RESOURCEBUTTON".equals(tableCode)) {
            codeName = "RESOURCEBUTTON_CODE";
        } else if ("JE_CORE_QUERYSTRATEGY".equals(tableCode)) {
            //策略按照名称
            codeName = "QUERYSTRATEGY_NAME";
        }
        String[] codeArray = new String[beans.size()];
        for (Integer i = 0; i < beans.size(); i++) {
            DynaBean bean = beans.get(i);
            codeArray[i] = bean.getStr(codeName, "");
        }
        metaService.executeSql("DELETE FROM " + tableCode + " WHERE " + foreignCode + "='" + softFunc.getStr("JE_CORE_FUNCINFO_ID") + "' AND " + codeName + " IN (" + StringUtil.buildArrayToString(codeArray) + ")");
    }

    @Override
    @Transactional
    public void updateTarget(String tableCode, DynaBean softFunc, DynaBean newBean) {
        String pkCode = metaBeanService.getPKeyFieldNames(tableCode);
        String foreignCode = getforeignCode(tableCode);
        String errors = "";
        DynaBean oldBean = null;
        //声明赋值字段，也就排除软连接的字段
        if ("JE_CORE_FUNCINFO".equals(tableCode)) {
            oldBean = softFunc;
        } else if ("JE_CORE_RESOURCECOLUMN".equals(tableCode)) {
            oldBean = metaService.selectOne("JE_CORE_RESOURCECOLUMN", ConditionsWrapper.builder()
                    .eq("RESOURCECOLUMN_FUNCINFO_ID", softFunc.getStr("JE_CORE_FUNCINFO_ID"))
                    .eq("RESOURCECOLUMN_CODE", newBean.getStr("RESOURCECOLUMN_CODE")));
            errors = "对应的列表字段【" + newBean.getStr("RESOURCECOLUMN_CODE") + "】";
        } else if ("JE_CORE_RESOURCEFIELD".equals(tableCode)) {
            oldBean = metaService.selectOne("JE_CORE_RESOURCEFIELD", ConditionsWrapper.builder()
                    .eq("RESOURCEFIELD_FUNCINFO_ID", softFunc.getStr("JE_CORE_FUNCINFO_ID"))
                    .eq("RESOURCEFIELD_CODE", newBean.getStr("RESOURCEFIELD_CODE")));
            errors = "对应的表单字段【" + newBean.getStr("RESOURCEFIELD_CODE") + "】";
        } else if ("JE_CORE_RESOURCEBUTTON".equals(tableCode)) {
            oldBean = metaService.selectOne("JE_CORE_RESOURCEBUTTON", ConditionsWrapper.builder()
                    .eq("RESOURCEBUTTON_FUNCINFO_ID", softFunc.getStr("JE_CORE_FUNCINFO_ID"))
                    .eq("RESOURCEBUTTON_CODE", newBean.getStr("RESOURCEBUTTON_CODE")));
            errors = "对应的按钮【" + newBean.getStr("RESOURCEBUTTON_CODE") + "】";
        } else if ("JE_CORE_QUERYSTRATEGY".equals(tableCode)) {
            //设置策略的功能编码
            newBean.set("QUERYSTRATEGY_FUNCCODE", softFunc.getStr("FUNCINFO_CODE"));
            oldBean = metaService.selectOne("JE_CORE_QUERYSTRATEGY", ConditionsWrapper.builder().eq("QUERYSTRATEGY_FUNCINFO_ID", softFunc.getStr("JE_CORE_FUNCINFO_ID")).eq("QUERYSTRATEGY_NAME", newBean.getStr("QUERYSTRATEGY_NAME")));
            errors = "对应的查询策略【" + newBean.getStr("QUERYSTRATEGY_NAME") + "】";
        }
        if (oldBean == null) {
            logger.error("未找到软连接功能【" + softFunc.getStr("FUNCINFO_FUNCNAME") + "】" + errors + "！");
            return;
        }
        newBean.set(BeanService.KEY_TABLE_CODE, tableCode);
        //赋值主键
        newBean.set(pkCode, oldBean.getStr(pkCode));
        //赋值功能外键
        if (StringUtil.isNotEmpty(foreignCode)) {
            newBean.set(foreignCode, softFunc.getStr("JE_CORE_FUNCINFO_ID"));
        }
        //获取赋值字段
        Set<String> fieldCodes = getFieldCodes(tableCode);
        //赋值
        for (String fieldCode : fieldCodes) {
            newBean.set(fieldCode, oldBean.get(fieldCode));
        }
        //更新实体
        if ("JE_CORE_RESOURCEFIELD".equals(tableCode)) {
            metaResFieldService.updateField(newBean);
        } else {
            metaService.update(newBean);
        }
    }

    @Override
    @Transactional
    public void insertTarget(String tableCode, DynaBean softFunc, DynaBean dynaBean) {
        String pkCode = metaBeanService.getPKeyFieldNames(tableCode);
        String foreignCode = getforeignCode(tableCode);
        if ("JE_CORE_QUERYSTRATEGY".equals(tableCode)) {
            //设置策略的功能编码
            dynaBean.set("QUERYSTRATEGY_FUNCCODE", softFunc.getStr("FUNCINFO_CODE"));
        }
        //构建创建信息
        commonService.buildModelCreateInfo(dynaBean);
        dynaBean.set(pkCode, null);
        dynaBean.set(foreignCode, softFunc.getStr("JE_CORE_FUNCINFO_ID"));
        dynaBean.set(BeanService.KEY_TABLE_CODE, tableCode);
        metaService.insert(dynaBean);
    }

    @Override
    public List<DynaBean> getRelyons(String funcId) {
        List<DynaBean> funcInfos = new ArrayList<DynaBean>();
        List<DynaBean> relyons = metaService.select("JE_CORE_FUNCRELYON", ConditionsWrapper.builder()
                .eq("FUNCRELYON_FUNCINFO_ID", funcId)
                .eq("FUNCRELYON_REGARD", FunCopyType.ZT).eq("FUNCRELYON_RELYTYPE", FunCopyType.ZXRLJ));
        for (DynaBean rel : relyons) {
            DynaBean one = metaService.selectOneByPk("JE_CORE_FUNCINFO", rel.getStr("FUNCRELYON_FUNCID"));
            if (one != null) {
                funcInfos.add(one);
            }
        }
        return funcInfos;
    }

    @Override
    public DynaBean checkCode(String strData) {
        DynaBean db = new DynaBean();
        String errorStr ="";
        JSONArray array = JSON.parseArray(strData);
        Iterator<Object> it = array.iterator();
        while (it.hasNext()){
            JSONObject jsonObject = (JSONObject) it.next();
            String FUNCRELATION_CODE = jsonObject.getString("FUNCRELATION_CODE");
            String JE_CORE_FUNCRELATION_ID = jsonObject.getString("JE_CORE_FUNCRELATION_ID");
            List<DynaBean> list = metaService.select("JE_CORE_FUNCRELATION",ConditionsWrapper.builder().eq("FUNCRELATION_CODE",FUNCRELATION_CODE));
            String itemId = list.get(0).getStr("JE_CORE_FUNCRELATION_ID");
            if(!itemId.equals(JE_CORE_FUNCRELATION_ID)){
                errorStr+=FUNCRELATION_CODE+",";
                array.remove(jsonObject);
            }
        }
        if(!StringUtil.isEmpty(errorStr)){
            db.setStr("errorSrr",errorStr);
        }
        if(array!=null&&array.size()>0){
            db.setStr("strData",array.toJSONString());
        }
        return db;
    }

    /**
     * 获取功能外键字段名
     *
     * @param tableCode
     * @return
     */
    private String getforeignCode(String tableCode) {
        String foreignCode = "";
        if ("JE_CORE_RESOURCECOLUMN".equals(tableCode)) {
            foreignCode = "RESOURCECOLUMN_FUNCINFO_ID";
        } else if ("JE_CORE_RESOURCEFIELD".equals(tableCode)) {
            foreignCode = "RESOURCEFIELD_FUNCINFO_ID";
        } else if ("JE_CORE_RESOURCEBUTTON".equals(tableCode)) {
            foreignCode = "RESOURCEBUTTON_FUNCINFO_ID";
        } else if ("JE_CORE_QUERYSTRATEGY".equals(tableCode)) {
            foreignCode = "QUERYSTRATEGY_FUNCINFO_ID";
        }
        return foreignCode;
    }

    private String getCode(String tableCode) {
        String code = "";
        if ("JE_CORE_RESOURCECOLUMN".equals(tableCode)) {
            code = "RESOURCECOLUMN_CODE";
        } else if ("JE_CORE_RESOURCEFIELD".equals(tableCode)) {
            code = "RESOURCEFIELD_CODE";
        } else if ("JE_CORE_RESOURCEBUTTON".equals(tableCode)) {
            code = "RESOURCEBUTTON_CODE";
        } else if ("JE_CORE_QUERYSTRATEGY".equals(tableCode)) {
            code = "QUERYSTRATEGY_NAME";
        } else if ("JE_CORE_FUNCINFO".equals(tableCode)) {
            code = "FUNCINFO_FUNCCODE";
        }
        return code;
    }

    /**
     * 获取更新需要赋值的字段     等同于不软连接字段
     *
     * @param tableCode
     * @return
     */
    private Set<String> getFieldCodes(String tableCode) {
        Set<String> fieldCodes = new HashSet<String>();
        //系统字段
        fieldCodes.add("SY_AUDFLAG");
        fieldCodes.add("SY_CREATEORGID");
        fieldCodes.add("SY_CREATEORGNAME");
        fieldCodes.add("SY_CREATETIME");
        fieldCodes.add("SY_CREATEUSERID");
        fieldCodes.add("SY_CREATEUSERNAME");
        fieldCodes.add("SY_FLAG");
//		fieldCodes.add("SY_MODIFYORG");
//		fieldCodes.add("SY_MODIFYORGNAME");
//		fieldCodes.add("SY_MODIFYUSER");
//		fieldCodes.add("SY_MODIFYUSERNAME");
//		fieldCodes.add("SY_MODIFYTIME");
        fieldCodes.add("SY_STATUS");
//		fieldCodes.add("SY_ORDERINDEX");
        fieldCodes.add("SY_PIID");
        fieldCodes.add("SY_PDID");
        fieldCodes.add("SY_PYJZ");
        fieldCodes.add("SY_PYQC");
        if ("JE_CORE_FUNCINFO".equals(tableCode)) {
            //路径
            fieldCodes.add("SY_PATH");
            //层次
            fieldCodes.add("SY_LAYER");
            //父节点id
            fieldCodes.add("SY_PARENT");
            //树形类型
            fieldCodes.add("SY_NODETYPE");
            //功能图标
            fieldCodes.add("FUNCINFO_ICON");
            //子系统
            fieldCodes.add("FUNCINFO_SUBSYSTEM_ID");
            //子系统
            fieldCodes.add("FUNCINFO_SYSTEMNAME");
            //是否静态化
            fieldCodes.add("FUNCINFO_ISSTATIC");
            //操作人
            fieldCodes.add("FUNCINFO_CHECKUSER");
            //操作人主键
            fieldCodes.add("FUNCINFO_CHECKUSERID");
            //操作人编码
            fieldCodes.add("FUNCINFO_CHECKUSERCODE");
            //操作状态
            fieldCodes.add("FUNCINFO_CHECKSTATUS");
            //版本
            fieldCodes.add("FUNCINFO_VERSION");
            //功能名称
            fieldCodes.add("FUNCINFO_FUNCNAME");
            //功能编码
            fieldCodes.add("FUNCINFO_FUNCCODE");
        }
        return fieldCodes;
    }

}
